<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>SpringBoot | Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="Spring Boot 学习笔记">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringBoot">
<meta property="og:url" content="http://example.com/2022/01/14/SpringBoot/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="Spring Boot 学习笔记">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2022-01-14T15:43:26.000Z">
<meta property="article:modified_time" content="2022-01-20T13:00:07.092Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 6.0.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-SpringBoot" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2022/01/14/SpringBoot/" class="article-date">
  <time class="dt-published" datetime="2022-01-14T15:43:26.000Z" itemprop="datePublished">2022-01-14</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="p-name article-title" itemprop="headline name">
      SpringBoot
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="Spring-Boot-学习笔记"><a href="#Spring-Boot-学习笔记" class="headerlink" title="Spring Boot 学习笔记"></a>Spring Boot 学习笔记</h1> <span id="more"></span> 

<h3 id="Spring-Boot"><a href="#Spring-Boot" class="headerlink" title="Spring Boot"></a>Spring Boot</h3><ul>
<li>做了什么  整合了所有的框架，去除大量的xml配置文件，简化复杂的依赖管理。</li>
</ul>
<hr>
<ul>
<li>目的  简化应用初始搭建及开发过程</li>
</ul>
<hr>
<ul>
<li>特点 <ol>
<li>独立运行Spring项目</li>
<li>内嵌Servlet容器</li>
<li>提供starter简化Maven配置</li>
<li>提供大量自动配置</li>
<li>自带应用监控</li>
<li>无代码生成和xml配置</li>
</ol>
</li>
</ul>
<hr>
<ul>
<li><p>创建Spring Boot项目方式</p>
<ol>
<li>Spring官网</li>
<li>Spring Initializer</li>
</ol>
<p>  运行***Application中的main()方法启动项目</p>
</li>
</ul>
<hr>
<h3 id="Spring-Boot-starter"><a href="#Spring-Boot-starter" class="headerlink" title="Spring Boot starter"></a>Spring Boot starter</h3><ul>
<li>starter 启动器 —约定大于配置</li>
</ul>
<hr>
<ul>
<li>yaml(yml)：以数据为中心的标记语言<ul>
<li>application.properties</li>
<li>application.yml</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot配置绑定"><a href="#Spring-Boot配置绑定" class="headerlink" title="Spring Boot配置绑定"></a>Spring Boot配置绑定</h3><ul>
<li>配置绑定：把配置文件中的值与JavaBean中对应的属性进行绑定</li>
<li>配置绑定的2种方式<ul>
<li>@ConfigurationProperties注解（1. @Component容器中的注解 2. prefix）</li>
<li>@Value注解（只需读取文件中的一个配置）</li>
</ul>
</li>
<li>2种方式对比：<ul>
<li>使用位置：<ul>
<li>标注在JavaBean类名上</li>
<li>标注在JavaBean属性上</li>
</ul>
</li>
<li>功能：<ul>
<li>用于绑定配置文件中的配置，</li>
<li>只能一个一个的指定需要绑定的配置</li>
</ul>
</li>
<li>松散绑定支持：前者支持，后者不支持</li>
<li>SpEL：<ul>
<li>不支持 SpEL 表达式</li>
<li>支持 SpEL 表达式。</li>
</ul>
</li>
<li>复杂类型封装：<ul>
<li>支持所有类型数据的封装，例如 Map、List、Set、以及对象等</li>
<li>只支持基本数据类型的封装，例如字符串、布尔值、整数等类型</li>
</ul>
</li>
<li>应用场景<ul>
<li>若只是获取配置文件中的某项值，则推荐使用 @Value 注解</li>
<li>若专门编写了一个 JavaBean 来和配置文件进行映射，则建议使用 @ConfigurationProperties 注解</li>
</ul>
</li>
</ul>
</li>
<li>@PropertySource：<ul>
<li>如果将所有的配置都集中到 application.properties 或 application.yml 中，那么这个配置文件会十分的臃肿且难以维护，因此我们通常会将与 Spring Boot 无关的配置（例如自定义配置）提取出来，写在一个单独的配置文件中，并在对应的 JavaBean 上使用 @PropertySource 注解指向该配置文件。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot导入Spring配置"><a href="#Spring-Boot导入Spring配置" class="headerlink" title="Spring Boot导入Spring配置"></a>Spring Boot导入Spring配置</h3><ul>
<li>2种方式<ul>
<li>@ImportResource 注解加载 Spring 配置</li>
<li>全注解方式加载 Spring 配置<ol>
<li>使用 @Configuration 注解定义配置类，替换 Spring 的配置文件；</li>
<li>配置类内部可以包含有一个或多个被 @Bean 注解的方法，这些方法会被 AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext 类扫描，构建 bean 定义（相当于 Spring 配置文件中的<bean></bean>标签），方法的返回值会以组件的形式添加到容器中，组件的 id 就是方法名。</li>
</ol>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot-Profile（多环境配置）"><a href="#Spring-Boot-Profile（多环境配置）" class="headerlink" title="Spring Boot Profile（多环境配置）"></a>Spring Boot Profile（多环境配置）</h3><ul>
<li>在实际的项目开发中，一个项目通常会存在多个环境，例如，开发环境、测试环境和生产环境等。不同环境的配置也不尽相同，例如开发环境使用的是开发数据库，测试环境使用的是测试数据库，而生产环境使用的是线上的正式数据库。</li>
<li>Profile 为在不同环境下使用不同的配置提供了支持，我们可以通过激活、指定参数等方式快速切换环境。</li>
<li>命名格式：application-{profile}.properties/yml</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">application.properties：主配置文件</span><br><span class="line">application-dev.properties：开发环境配置文件</span><br><span class="line">application-test.properties：测试环境配置文件</span><br><span class="line">application-prod.properties：生产环境配置文件</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">application.yml：默认配置</span><br><span class="line">application-dev.yml：开发环境配置</span><br><span class="line">application-test.yml：测试环境配置</span><br><span class="line">application-prod.yml：生产环境配置</span><br></pre></td></tr></table></figure>
<ul>
<li>在 YAML 配置文件中，可以使用“—”把配置文件分割成了多个文档块，因此我们可以在不同的文档块中针对不同的环境进行不同的配置，并在第一个文档块内对配置进行切换。</li>
<li>激活 Profile<ul>
<li>命令行激活</li>
<li>虚拟机参数激活</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot默认配置文件"><a href="#Spring-Boot默认配置文件" class="headerlink" title="Spring Boot默认配置文件"></a>Spring Boot默认配置文件</h3><ul>
<li>Spring Boot 项目中可以存在多个 application.properties 或 apllication.yml。</li>
<li>Spring Boot 启动时会扫描以下 5 个位置的  application.properties 或 apllication.yml 文件，并将它们作为 Spring boot 的默认配置文件。 <ol>
<li>file:./config/</li>
<li>file:./config/*/</li>
<li>lasspath:/config/</li>
<li>classpath:/</li>
</ol>
</li>
<li>以上所有位置的配置文件都会被加载，且它们优先级依次降低，序号越小优先级越高。其次，位于相同位置的 application.properties 的优先级高于 application.yml。</li>
<li>所有位置的文件都会被加载，高优先级配置会覆盖低优先级配置，形成互补配置，即：<ul>
<li>存在相同的配置内容时，高优先级的内容会覆盖低优先级的内容；</li>
<li>存在不同的配置内容时，高优先级和低优先级的配置内容取并集。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot外部配置文件"><a href="#Spring-Boot外部配置文件" class="headerlink" title="Spring Boot外部配置文件"></a>Spring Boot外部配置文件</h3><ul>
<li>除了默认配置文件，Spring Boot 还可以加载一些位于项目外部的配置文件。我们可以通过如下 2 个参数，指定外部配置文件的路径：<ul>
<li>spring.config.location<ul>
<li>使用该参数指定配置文件后，会使项目默认配置文件（application.properties 或 application.yml ）失效，Spring Boot 将只加载指定的外部配置文件。</li>
</ul>
</li>
<li>spring.config.additional-location<ul>
<li>不会使项目默认的配置文件失效，使用该命令行参数添加的外部配置文件会与项目默认的配置文件共同生效，形成互补配置，且其优先级是最高的，比所有默认配置文件的优先级都高。 </li>
</ul>
</li>
</ul>
</li>
<li>注意：Maven 对项目进行打包时，位于项目根目录下的配置文件是无法被打包进项目的 JAR 包的，因此位于根目录下的默认配置文件无法在 JAR 中生效，即该项目将只加载指定的外部配置文件和项目类路径（classpath）下的默认配置文件，它们的加载优先级顺序为：<ol>
<li>spring.config.additional-location 指定的外部配置文件 my-application.yml</li>
<li>classpath:/config/application.yml</li>
<li>classpath:/application.yml</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot配置加载顺序"><a href="#Spring-Boot配置加载顺序" class="headerlink" title="Spring Boot配置加载顺序"></a>Spring Boot配置加载顺序</h3><ul>
<li>Spring Boot 不仅可以通过配置文件进行配置，还可以通过环境变量、命令行参数等多种形式进行配置。这些配置都可以让开发人员在不修改任何代码的前提下，直接将一套 Spring Boot  应用程序在不同的环境中运行。</li>
<li>Spring Boot 配置优先级（优先级由高到低）以下所有形式的配置都会被加载，当存在相同配置内容时，高优先级的配置会覆盖低优先级的配置；存在不同的配置内容时，高优先级和低优先级的配置内容取并集，共同生效，形成互补配置。<ol>
<li>命令行参数</li>
<li>来自 java:comp/env 的 JNDI 属性</li>
<li>Java 系统属性（System.getProperties()）</li>
<li>操作系统环境变量</li>
<li>RandomValuePropertySource 配置的 random.* 属性值</li>
<li>配置文件（YAML 文件、Properties 文件）</li>
<li>@Configuration 注解类上的 @PropertySource 指定的配置文件</li>
<li>通过 SpringApplication.setDefaultProperties 指定的默认属性</li>
</ol>
</li>
<li>Spring Boot 启动时，会自动加载 JAR 包内部及 JAR 包所在目录指定位置的配置文件（Properties 文件、YAML 文件），以下展示了 Spring Boot 自动加载的配置文件的位置及其加载顺序，同一位置下，同一位置下，Properties 文件优先级高于 YAML 文件。<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">/myBoot</span><br><span class="line">    /config</span><br><span class="line">        /childDir</span><br><span class="line">            appliaction-&#123;profile&#125;.properties.yml--------1</span><br><span class="line">            appliaction.properties/yml------------------2</span><br><span class="line">        appliaction-&#123;profile&#125;.properties.yml------------3</span><br><span class="line">        appliaction.properties.yml----------------------4</span><br><span class="line">    appliaction-&#123;profile&#125;.properties.yml----------------5</span><br><span class="line">    appliaction.properties.yml--------------------------6</span><br><span class="line">    /JAR</span><br><span class="line">        /resources</span><br><span class="line">            /config</span><br><span class="line">                appliaction-&#123;profile&#125;.properties.yml----7</span><br><span class="line">                appliaction.properties.yml--------------8</span><br><span class="line">        appliaction-&#123;profile&#125;.properties.yml------------9</span><br><span class="line">        appliaction.properties.yml----------------------10</span><br></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">说明：</span><br><span class="line">/myBoot：表示 JAR 包所在目录，目录名称自定义；</span><br><span class="line">/childDir：表示 JAR 包所在目录下 config 目录的子目录，目录名自定义；</span><br><span class="line">JAR：表示 Spring Boot 项目打包生成的 JAR；</span><br><span class="line">其余带有“/”标识的目录的目录名称均不能修改。</span><br><span class="line">红色数字：表示该配置文件的优先级，数字越小优先级越高。</span><br><span class="line"></span><br><span class="line">这些配置文件得优先级顺序，遵循以下规则：</span><br><span class="line">先加载 JAR 包外的配置文件，再加载 JAR 包内的配置文件；</span><br><span class="line">先加载 config 目录内的配置文件，再加载 config 目录外的配置文件；</span><br><span class="line">先加载 config 子目录下的配置文件，再加载 config 目录下的配置文件；</span><br><span class="line">先加载 appliction-&#123;profile&#125;.properties/yml，再加载 application.properties/yml；</span><br><span class="line">先加载 .properties 文件，再加载 .yml 文件。</span><br></pre></td></tr></table></figure></li>
</ul>
<hr>
<h3 id="Spring-Boot自动配置原理"><a href="#Spring-Boot自动配置原理" class="headerlink" title="Spring Boot自动配置原理"></a>Spring Boot自动配置原理</h3><h4 id="Spring-Factories-机制—Spring-Boot-的自动配置是基于-Spring-Factories-机制实现的"><a href="#Spring-Factories-机制—Spring-Boot-的自动配置是基于-Spring-Factories-机制实现的" class="headerlink" title="Spring Factories 机制—Spring Boot 的自动配置是基于 Spring Factories 机制实现的"></a>Spring Factories 机制—Spring Boot 的自动配置是基于 Spring Factories 机制实现的</h4><ul>
<li><p>Spring Factories 机制是 Spring Boot 中的一种服务发现机制，这种扩展机制与 Java SPI 机制十分相似。</p>
</li>
<li><p>Spring Boot 会自动扫描所有 Jar 包类路径下 META-INF/spring.factories 文件，并读取其中的内容，进行实例化，这种机制也是 Spring Boot Starter 的基础。</p>
</li>
<li><p>spring.factories 文件本质上与 properties 文件相似，其中包含一组或多组键值对（key=vlaue），其中，key 的取值为接口的完全限定名；value 的取值为接口实现类的完全限定名，一个接口可以设置多个实现类，不同实现类之间使用“，”隔开，例如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\</span><br><span class="line">org.springframework.boot.autoconfigure.condition.OnBeanCondition,\</span><br><span class="line">org.springframework.boot.autoconfigure.condition.OnClassCondition,\</span><br><span class="line">org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition</span><br><span class="line">//注意：文件中配置的内容过长，为了阅读方便而手动换行时，为了防止内容丢失可以使用“\”</span><br></pre></td></tr></table></figure>
<h4 id="Spring-Factories-实现原理"><a href="#Spring-Factories-实现原理" class="headerlink" title="Spring Factories 实现原理"></a>Spring Factories 实现原理</h4></li>
<li><p>spring-core 包里定义了 SpringFactoriesLoader 类，这个类会扫描所有 Jar 包类路径下的 META-INF/spring.factories 文件，并获取指定接口的配置。在 SpringFactoriesLoader 类中定义了两个对外的方法:</p>
<ul>
<li>loadFactories(静态方法，根据接口获取其实现类的实例，该方法返回的是实现类对象列表。)</li>
<li>loadFactoryNames（公共静态方法，根据接口l获取其实现类的名称，该方法返回的是实现类的类名的列表）<h4 id="自动配置的加载"><a href="#自动配置的加载" class="headerlink" title="自动配置的加载"></a>自动配置的加载</h4></li>
</ul>
</li>
<li><p>Spring Boot 自动化配置也是基于 Spring Factories 机制实现的，在 spring-boot-autoconfigure-xxx.jar 类路径下的 META-INF/spring.factories 中设置了 Spring Boot 自动配置的内容，每个 xxxAutoConfiguration 都是一个自动配置类。Spring Boot 启动时，会利用 Spring-Factories 机制，将这些 xxxAutoConfiguration 实例化并作为组件加入到容器中，以实现 Spring Boot 的自动配置。</p>
<h4 id="SpringBootApplication-注解"><a href="#SpringBootApplication-注解" class="headerlink" title="@SpringBootApplication 注解"></a>@SpringBootApplication 注解</h4></li>
<li><p>所有 Spring Boot 项目的主启动程序类上都使用了一个 @SpringBootApplication 注解，该注解是 Spring Boot 中最重要的注解之一 ，也是 Spring Boot 实现自动化配置的关键。</p>
</li>
<li><p>@SpringBootApplication 是一个组合元注解，其主要包含两个注解：</p>
<ul>
<li>@SpringBootConfiguration </li>
<li>@EnableAutoConfiguration</li>
</ul>
<p>  其中 @EnableAutoConfiguration 注解是 SpringBoot 自动化配置的核心所在。</p>
<h4 id="EnableAutoConfiguration-注解"><a href="#EnableAutoConfiguration-注解" class="headerlink" title="@EnableAutoConfiguration 注解"></a>@EnableAutoConfiguration 注解</h4></li>
<li><p>用于开启 Spring Boot 的自动配置功能， 它使用 Spring 框架提供的 @Import 注解通过 AutoConfigurationImportSelector类（选择器）给容器中导入自动配置组件。</p>
<h4 id="AutoConfigurationImportSelector-类"><a href="#AutoConfigurationImportSelector-类" class="headerlink" title="AutoConfigurationImportSelector 类"></a>AutoConfigurationImportSelector 类</h4></li>
<li><p>AutoConfigurationImportSelector 类实现了 DeferredImportSelector 接口，AutoConfigurationImportSelector 中还包含一个静态内部类 AutoConfigurationGroup，它实现了 DeferredImportSelector 接口的内部接口 Group（Spring 5 新增）。</p>
</li>
<li><p>AutoConfigurationImportSelector 类中包含 3 个方法</p>
<ul>
<li>getImportGroup()//用于获取实现了 DeferredImportSelector.Group 接口的类</li>
<li>process() //静态内部类 AutoConfigurationGroup 中的核心方法是 process()，该方法通过调用 getAutoConfigurationEntry() 方法读取 spring.factories 文件中的内容，获得自动配置类的集合</li>
<li>selectImports()//通过调用 getCandidateConfigurations() 方法来获取自动配置类的完全限定名，并在经过排除、过滤等处理后，将其缓存到成员变量中</li>
</ul>
<hr>
<ul>
<li>在 getCandidateConfigurations() 方法中，根据 Spring Factories 机制调用 SpringFactoriesLoader 的 loadFactoryNames() 方法，根据 EnableAutoConfiguration.class （自动配置接口）获取其实现类（自动配置类）的类名的集合</li>
<li>以上所有方法执行完成后，AutoConfigurationImportSelector.AutoConfigurationGroup#selectImports() 会将 process() 方法处理后得到的自动配置类，进行过滤、排除，最后将所有自动配置类添加到容器中<h4 id="自动配置的生效和修改"><a href="#自动配置的生效和修改" class="headerlink" title="自动配置的生效和修改"></a>自动配置的生效和修改</h4></li>
</ul>
</li>
<li><p>spring.factories 文件中的所有自动配置类（xxxAutoConfiguration），都是必须在一定的条件下才会作为组件添加到容器中，配置的内容才会生效。这些限制条件在 Spring Boot 中以 @Conditional 派生注解的形式体现</p>
<table>
<thead>
<tr>
<th align="left">注解</th>
<th align="left">生效条件</th>
</tr>
</thead>
<tbody><tr>
<td align="left">@ConditionalOnJava</td>
<td align="left">应用使用指定的 Java 版本时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnBean</td>
<td align="left">容器中存在指定的  Bean 时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnMissingBean</td>
<td align="left">容器中不存在指定的 Bean 时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnExpression</td>
<td align="left">满足指定的 SpEL 表达式时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnClass</td>
<td align="left">存在指定的类时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnMissingClass</td>
<td align="left">不存在指定的类时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnSingleCandidate</td>
<td align="left">容器中只存在一个指定的 Bean 或这个 Bean 为首选 Bean 时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnProperty</td>
<td align="left">系统中指定属性存在指定的值时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnResource</td>
<td align="left">类路径下存在指定的资源文件时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnWebApplication</td>
<td align="left">当前应用是 web 应用时生效</td>
</tr>
<tr>
<td align="left">@ConditionalOnNotWebApplication</td>
<td align="left">当前应用不是 web 应用生效</td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="ServerProperties"><a href="#ServerProperties" class="headerlink" title="ServerProperties"></a>ServerProperties</h4><ul>
<li><p>Spring Boot 中为我们提供了大量的自动配置类 XxxAutoConfiguration 以及 XxxProperties，每个自动配置类 XxxAutoConfiguration 都使用了 @EnableConfigurationProperties 注解，而每个 XxxProperties 上都使用 @ConfigurationProperties 注解。</p>
</li>
<li><p>@ConfigurationProperties 注解的作用，是将这个类的所有属性与配置文件中相关的配置进行绑定，以便于获取或修改配置，但是 @ConfigurationProperties 功能是由容器提供的，被它注解的类必须是容器中的一个组件，否则该功能就无法使用。而 @EnableConfigurationProperties 注解的作用正是将指定的类以组件的形式注入到 IOC 容器中，并开启其 @ConfigurationProperties 功能。因此，@ConfigurationProperties + @EnableConfigurationProperties 组合使用，便可以为 XxxProperties 类实现配置绑定功能。</p>
</li>
<li><p>自动配置类 XxxAutoConfiguration 负责使用 XxxProperties 中属性进行自动配置，而 XxxProperties 则负责将自动配置属性与配置文件的相关配置进行绑定，以便于用户通过配置文件修改默认的自动配置。也就是说，真正“限制”我们可以在配置文件中配置哪些属性的类就是这些 XxxxProperties 类，它与配置文件中定义的 prefix 关键字开头的一组属性是唯一对应的。 </p>
</li>
<li><p>注意：XxxAutoConfiguration 与 XxxProperties 并不是一一对应的，大多数情况都是多对多的关系，即一个 XxxAutoConfiguration 可以同时使用多个 XxxProperties 中的属性，一个 XxxProperties 类中属性也可以被多个 XxxAutoConfiguration 使用。</p>
</li>
</ul>
<hr>
<h3 id="Spring-Boot统一日志框架"><a href="#Spring-Boot统一日志框架" class="headerlink" title="Spring Boot统一日志框架"></a>Spring Boot统一日志框架</h3><ul>
<li><p>日志框架分为2类</p>
<ul>
<li><p>日志门面：为 Java 日志访问提供一套标准和规范的 API 框架，其主要意义在于提供接口。（JCL（Jakarta Commons Logging）、SLF4j（Simple Logging Facade for Java）、jboss-logging）</p>
</li>
<li><p>日志实现：日志门面的具体的实现（Log4j、JUL（java.util.logging）、Log4j2、Logback）</p>
</li>
</ul>
</li>
<li><p>通常情况下，日志由一个日志门面与一个日志实现组合搭建而成，Spring Boot 选用 SLF4J + Logback 的组合来搭建日志系统。</p>
</li>
<li><p>SLF4J 是目前市面上最流行的日志门面，使用 Slf4j 可以很灵活的使用占位符进行参数占位，简化代码，拥有更好的可读性。</p>
</li>
<li><p>Logback 是 Slf4j 的原生实现框架，它与 Log4j 出自一个人之手，但拥有比 log4j 更多的优点、特性和更做强的性能，现在基本都用来代替 log4j 成为主流。</p>
</li>
<li><p>统一日志框架（通用）</p>
<ol>
<li>排除应用中的原来的日志框架；</li>
<li>引入替换包替换被排除的日志框架；</li>
<li>导入 SLF4J 实现。</li>
</ol>
</li>
<li><p>统一日志框架（Spring Boot）</p>
<ul>
<li>统一日志框架的使用一共分为 3 步，Soring Boot 作为一款优秀的开箱即用的框架，已经为用户完成了其中 2 步：引入替换包和导入 SLF4J 实现。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot日志配置及输出"><a href="#Spring-Boot日志配置及输出" class="headerlink" title="Spring Boot日志配置及输出"></a>Spring Boot日志配置及输出</h3><h4 id="默认配置"><a href="#默认配置" class="headerlink" title="默认配置"></a>默认配置</h4><ul>
<li><p>Spring Boot 默认使用 SLF4J+Logback 记录日志，并提供了默认配置，即使我们不进行任何额外配，也可以使用 SLF4J+Logback 进行日志输出。</p>
</li>
<li><p>常见的日志配置包括日志级别、日志的输入出格式等内容。</p>
</li>
</ul>
<h6 id="日志级别"><a href="#日志级别" class="headerlink" title="日志级别"></a>日志级别</h6><ul>
<li><p>日志的输出都是分级别的，当一条日志信息的级别大于或等于配置文件的级别时，就对这条日志进行记录。<br>常见的日志级别如下（优先级依次升高）。</p>
<table>
<thead>
<tr>
<th align="center">序号</th>
<th align="left">日志级别</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="left">trace</td>
<td align="left">追踪，指明程序运行轨迹。</td>
</tr>
<tr>
<td align="center">2</td>
<td align="left">debug</td>
<td align="left">调试，实际应用中一般将其作为最低级别，而 trace 则很少使用。</td>
</tr>
<tr>
<td align="center">3</td>
<td align="left">info</td>
<td align="left">输出重要的信息，使用较多。</td>
</tr>
<tr>
<td align="center">4</td>
<td align="left">warn</td>
<td align="left">警告，使用较多。</td>
</tr>
<tr>
<td align="center">5</td>
<td align="left">error</td>
<td align="left">错误信息，使用较多。</td>
</tr>
</tbody></table>
</li>
</ul>
<h5 id="输出格式"><a href="#输出格式" class="headerlink" title="输出格式"></a>输出格式</h5><table>
<thead>
<tr>
<th align="center">序号</th>
<th align="left">输出格式</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="center">1</td>
<td align="left">%d{yyyy-MM-dd HH:mm:ss, SSS}</td>
<td align="left">日志生产时间,输出到毫秒的时间</td>
</tr>
<tr>
<td align="center">2</td>
<td align="left">%-5level</td>
<td align="left">输出日志级别，-5 表示左对齐并且固定输出 5 个字符，如果不足在右边补 0</td>
</tr>
<tr>
<td align="center">3</td>
<td align="left">%logger 或 %c</td>
<td align="left">logger 的名称</td>
</tr>
<tr>
<td align="center">4</td>
<td align="left">%thread  或 %t</td>
<td align="left">输出当前线程名称</td>
</tr>
<tr>
<td align="center">5</td>
<td align="left">%p</td>
<td align="left">日志输出格式</td>
</tr>
<tr>
<td align="center">6</td>
<td align="left">%message 或 %msg 或 %m</td>
<td align="left">日志内容，即 logger.info(“message”)</td>
</tr>
<tr>
<td align="center">7</td>
<td align="left">%n</td>
<td align="left">换行符</td>
</tr>
<tr>
<td align="center">8</td>
<td align="left">%class 或 %C</td>
<td align="left">输出 Java 类名</td>
</tr>
<tr>
<td align="center">9</td>
<td align="left">%file 或 %F</td>
<td align="left">输出文件名</td>
</tr>
<tr>
<td align="center">10</td>
<td align="left">%L</td>
<td align="left">输出错误行号</td>
</tr>
<tr>
<td align="center">11</td>
<td align="left">%method 或 %M</td>
<td align="left">输出方法名</td>
</tr>
<tr>
<td align="center">12</td>
<td align="left">%l</td>
<td align="left">输出语句所在的行数, 包括类名、方法名、文件名、行数</td>
</tr>
<tr>
<td align="center">13</td>
<td align="left">hostName</td>
<td align="left">本地机器名</td>
</tr>
<tr>
<td align="center">14</td>
<td align="left">hostAddress</td>
<td align="left">本地 ip 地址</td>
</tr>
</tbody></table>
<h4 id="修改默认日志配置"><a href="#修改默认日志配置" class="headerlink" title="修改默认日志配置"></a>修改默认日志配置</h4><ul>
<li><p>可以根据自身的需求，通过全局配置文件（application.properties/yml）修改 Spring Boot 日志级别和显示格式等默认配置。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">#日志级别</span><br><span class="line">logging.level.net.biancheng.www=trace</span><br><span class="line">#使用相对路径的方式设置日志输出的位置（项目根目录目录\my-log\mylog\spring.log）</span><br><span class="line">#logging.file.path=my-log/myLog</span><br><span class="line">#绝对路径方式将日志文件输出到 【项目所在磁盘根目录\springboot\logging\my\spring.log】</span><br><span class="line">logging.file.path=/spring-boot/logging</span><br><span class="line">#控制台日志输出格式</span><br><span class="line">logging.pattern.console=%d&#123;yyyy-MM-dd hh:mm:ss&#125; [%thread] %-5level %logger&#123;50&#125; - %msg%n</span><br><span class="line">#日志文件输出格式</span><br><span class="line">logging.pattern.file=%d&#123;yyyy-MM-dd&#125; === [%thread] === %-5level === %logger&#123;50&#125; === - %msg%n</span><br></pre></td></tr></table></figure>
<h4 id="自定义日志配置"><a href="#自定义日志配置" class="headerlink" title="自定义日志配置"></a>自定义日志配置</h4></li>
<li><p>在 Spring Boot 的配置文件 application.porperties/yml 中，可以对日志的一些默认配置进行修改，但这种方式只能修改个别的日志配置，想要修改更多的配置或者使用更高级的功能，则需要通过日志实现框架自己的配置文件进行配置。</p>
</li>
<li><p>Spring 官方提供了各个日志实现框架所需的配置文件，用户只要将指定的配置文件放置到项目的类路径下即可。</p>
</li>
</ul>
<table>
<thead>
<tr>
<th align="left">日志框架</th>
<th align="left">配置文件</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Logback</td>
<td align="left">logback-spring.xml、logback-spring.groovy、logback.xml、logback.groovy</td>
</tr>
<tr>
<td align="left">Log4j2</td>
<td align="left">log4j2-spring.xml、log4j2.xml</td>
</tr>
<tr>
<td align="left">JUL (Java Util Logging)</td>
<td align="left">logging.properties</td>
</tr>
</tbody></table>
<ul>
<li>日志框架的配置文件基本上被分为 2 类：<ul>
<li>普通日志配置文件，即不带 srping 标识的配置文件，例如 logback.xml；<ul>
<li>将 logback.xml、log4j2.xml 等不带 spring 标识的普通日志配置文件，放在项目的类路径下后，这些配置文件会跳过 Spring Boot，直接被日志框架加载。通过这些配置文件，我们就可以达到自定义日志配置的目的。</li>
</ul>
</li>
<li>带有 spring 表示的日志配置文件，例如 logback-spring.xml。<ul>
<li>Spring Boot 推荐用户使用 logback-spring.xml、log4j2-spring.xml 等这种带有 spring 标识的配置文件。这种配置文件被放在项目类路径后，不会直接被日志框架加载，而是由 Spring Boot 对它们进行解析，这样就可以使用 Spring Boot 的高级功能 Profile，实现在不同的环境中使用不同的日志配置。 </li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="spring-boot-starter-web（Web启动器）"><a href="#spring-boot-starter-web（Web启动器）" class="headerlink" title="spring-boot-starter-web（Web启动器）"></a>spring-boot-starter-web（Web启动器）</h3><ul>
<li><p>Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架，其本身就是 Spring 框架的一部分，可以与 Spring 无缝集成，性能方面具有先天的优越性，是当今业界最主流的 Web 开发框架之一。</p>
</li>
<li><p>Spring Boot 是在 Spring 的基础上创建一款开源框架，它提供了 spring-boot-starter-web（Web 场景启动器） 来为 Web 开发予以支持。</p>
</li>
<li><p>spring-boot-starter-web 为我们提供了嵌入的 Servlet 容器以及 SpringMVC 的依赖，并为 Spring MVC 提供了大量自动配置，可以适用于大多数 Web 开发场景。</p>
</li>
</ul>
<h4 id="Spring-Boot-Web-快速开发"><a href="#Spring-Boot-Web-快速开发" class="headerlink" title="Spring Boot Web 快速开发"></a>Spring Boot Web 快速开发</h4><p>Spring Boot 为 Spring MVC 提供了自动配置，并在 Spring MVC 默认功能的基础上添加了以下特性：</p>
<ul>
<li>引入了 ContentNegotiatingViewResolver 和 BeanNameViewResolver（视图解析器）</li>
<li>对包括 WebJars 在内的静态资源的支持</li>
<li>自动注册 Converter、GenericConverter 和 Formatter （转换器和格式化器）</li>
<li>对 HttpMessageConverters 的支持（Spring MVC 中用于转换 HTTP 请求和响应的消息转换器）</li>
<li>自动注册 MessageCodesResolver（用于定义错误代码生成规则）</li>
<li>支持对静态首页（index.html）的访问</li>
<li>自动使用 ConfigurableWebBindingInitializer</li>
</ul>
<p>只要我们在 Spring  Boot 项目中的 pom.xml 中引入了 spring-boot-starter-web ，即使不进行任何配置，也可以直接使用 Spring MVC 进行 Web 开发。</p>
<hr>
<h3 id="Spring-Boot静态资源映射"><a href="#Spring-Boot静态资源映射" class="headerlink" title="Spring Boot静态资源映射"></a>Spring Boot静态资源映射</h3><ul>
<li><p>在 Web 应用中会涉及到大量的静态资源，例如 JS、CSS 和 HTML 等。我们知道，Spring MVC 导入静态资源文件时，需要配置静态资源的映射；但在 SpringBoot 中则不再需要进行此项配置，因为 SpringBoot 已经默认完成了这一工作。</p>
</li>
<li><p>Spring Boot 默认为我们提供了 3 种静态资源映射规则：</p>
<ul>
<li><p>WebJars 映射</p>
<ul>
<li><p>WebJars 可以将 Web 前端资源（JS，CSS 等）打成一个个的 Jar 包，然后将这些 Jar 包部署到 Maven 中央仓库中进行统一管理，当 Spring Boot 项目中需要引入 Web 前端资源时，只需要访问 WebJars 官网，找到所需资源的 pom 依赖，将其导入到项目中即可。</p>
</li>
<li><p>所有通过 WebJars 引入的前端资源都存放在当前项目类路径（classpath）下的“/META-INF/resources/webjars/” 目录中。</p>
</li>
</ul>
</li>
<li><p>默认资源映射</p>
<ul>
<li><p>当访问项目中的任意资源（即“/**”）时，Spring Boot 会默认从以下路径中查找资源文件（优先级依次降低）：</p>
<blockquote>
</blockquote>
<ol>
<li>classpath:/META-INF/resources/</li>
<li>classpath:/resources/</li>
<li>classpath:/static/</li>
<li>classpath:/public/</li>
</ol>
</li>
<li><p>这些路径又被称为静态资源文件夹，它们的优先级顺序为：classpath:/META-INF/resources/ &gt; classpath:/resources/ &gt; classpath:/static/ &gt; classpath:/public/ 。</p>
</li>
<li><p>当我们请求某个静态资源（即以“.html”结尾的请求）时，Spring Boot 会先查找优先级高的文件夹，再查找优先级低的文件夹，直到找到指定的静态资源为止。</p>
</li>
</ul>
</li>
<li><p>静态首页（欢迎页）映射</p>
<ul>
<li><p>静态资源文件夹下的所有 index.html 被称为静态首页或者欢迎页，它们会被被 /** 映射，换句话说就是，当我们访问“/”或者“/index.html”时，都会跳转到静态首页（欢迎页）。</p>
</li>
<li><p>注意，访问静态首页或欢迎页时，其查找顺序也遵循默认静态资源的查找顺序，即先查找优先级高的目录，在查找优先级低的目录，直到找到 index.html 为止。</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot定制Spring-MVC"><a href="#Spring-Boot定制Spring-MVC" class="headerlink" title="Spring Boot定制Spring MVC"></a>Spring Boot定制Spring MVC</h3><ul>
<li><p>Spring Boot 抛弃了传统 xml 配置文件，通过配置类（标注 @Configuration 的类，相当于一个 xml 配置文件）以 JavaBean 形式进行相关配置。</p>
</li>
<li><p>Spring Boot 对 Spring MVC 的自动配置可以满足我们的大部分需求，但是我们也可以通过自定义配置类（标注 @Configuration 的类）并实现 WebMvcConfigurer 接口来定制 Spring MVC 配置，例如拦截器、格式化程序、视图控制器等等。</p>
</li>
<li><p>SpringBoot 1.5 及以前是通过继承 WebMvcConfigurerAdapter 抽象类来定制 Spring MVC 配置的，但在 SpringBoot 2.0 后，WebMvcConfigurerAdapter 抽象类就被弃用了，改为实现 WebMvcConfigurer 接口来定制 Spring MvVC 配置。</p>
</li>
<li><p>WebMvcConfigurer 是一个基于 Java  8 的接口，该接口定义了许多与 Spring MVC 相关的方法，其中大部分方法都是 default 类型的，且都是空实现。因此我们只需要定义一个配置类实现 WebMvcConfigurer 接口，并重写相应的方法便可以定制 Spring MVC 的配置。</p>
</li>
<li><p>在 Spring Boot 项目中，我们可以通过以下 2 中形式定制 Spring MVC:</p>
<ul>
<li><p>扩展 Spring MVC</p>
<ul>
<li>如果 Spring Boot 对 Spring MVC 的自动配置不能满足我们的需要，我们还可以通过自定义一个 WebMvcConfigurer 类型（实现 WebMvcConfigurer 接口）的配置类（标注 @Configuration，但不标注 @EnableWebMvc 注解的类），来扩展 Spring MVC。这样不但能够保留 Spring Boot 对 Spring MVC 的自动配置，享受 Spring  Boot 自动配置带来的便利，还能额外增加自定义的 Spring MVC 配置。 </li>
</ul>
</li>
<li><p>全面接管 Spring MVC</p>
<ul>
<li><p>在一些特殊情况下，我们可能需要抛弃 Spring Boot 对 Spring MVC 的全部自动配置，完全接管 Spring MVC。此时我们可以自定义一个 WebMvcConfigurer 类型（实现 WebMvcConfigurer 接口）的配置类，并在该类上标注 @EnableWebMvc 注解，来实现完全接管 Spring MVC。</p>
</li>
<li><p>注意：完全接管 Spring MVC 后，Spring Boot 对 Spring MVC 的自动配置将全部失效。</p>
</li>
<li><p>Spring Boot 能够访问位于静态资源文件夹中的静态文件，这是在 Spring Boot 对 Spring MVC 的默认自动配置中定义的，当我们全面接管 Spring MVC 后，Spring Boot 对 Spring MVC 的默认配置都会失效，此时再访问静态资源文件夹中的静态资源就会报 404 错误。</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Thymeleaf"><a href="#Thymeleaf" class="headerlink" title="Thymeleaf"></a>Thymeleaf</h3><ul>
<li><p>Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP，Velocity，FreeMaker 等模板引擎类似，也可以轻易地与 Spring MVC 等 Web 框架集成。与其它模板引擎相比，Thymeleaf 最大的特点是，即使不启动 Web 应用，也可以直接在浏览器中打开并正确显示模板页面 。</p>
</li>
<li><p>Thymeleaf 是新一代 Java 模板引擎，与 Velocity、FreeMarker 等传统 Java 模板引擎不同，Thymeleaf 支持 HTML 原型，其文件后缀为“.html”，因此它可以直接被浏览器打开，此时浏览器会忽略未定义的 Thymeleaf 标签属性，展示 thymeleaf 模板的静态页面效果；当通过 Web 应用程序访问时，Thymeleaf 会动态地替换掉静态内容，使页面动态显示。</p>
</li>
<li><p>Thymeleaf 的特点（Thymeleaf 模板引擎具有以下特点：）</p>
<ul>
<li>动静结合：Thymeleaf 既可以直接使用浏览器打开，查看页面的静态效果，也可以通过 Web 应用程序进行访问，查看动态页面效果。</li>
<li>开箱即用：Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块，可以快速的实现表单绑定、属性编辑器、国际化等功能。</li>
<li>多方言支持：它提供了 Thymeleaf 标准和 Spring 标准两种方言，可以直接套用模板实现 JSTL、 OGNL 表达式；必要时，开发人员也可以扩展和创建自定义的方言。</li>
<li>与 SpringBoot 完美整合：SpringBoot 为 Thymeleaf 提供了的默认配置，并且还为 Thymeleaf 设置了视图解析器，因此 Thymeleaf 可以与 Spring Boot 完美整合。</li>
</ul>
</li>
<li><p>Thymeleaf 语法规则</p>
<ul>
<li><p>在使用 Thymeleaf 之前，首先要在页面的 html 标签中声明名称空间，示例代码如下<br><code>xmlns:th=&quot;http://www.thymeleaf.org&quot;</code></p>
</li>
<li><p>在 html 标签中声明此名称空间，可避免编辑器出现 html 验证错误，但这一步并非必须进行的，即使我们不声明该命名空间，也不影响 Thymeleaf 的使用。</p>
</li>
<li><p>Thymeleaf 语法分为以下 2 类：</p>
<ul>
<li>标准表达式语法<ul>
<li>Thymeleaf 模板引擎支持多种表达式<ul>
<li>变量表达式：${…}<ul>
<li>使用 ${} 包裹的表达式被称为变量表达式，该表达式具有以下功能：<ul>
<li>获取对象的属性和方法</li>
<li>使用内置的基本对象</li>
<li>使用内置的工具对象</li>
</ul>
</li>
</ul>
</li>
<li>选择变量表达式：*{…}</li>
<li>链接表达式：@{…}</li>
<li>国际化表达式：#{…}</li>
<li>片段引用表达式：~{…}</li>
</ul>
</li>
</ul>
</li>
<li>th 属性<ul>
<li>Thymeleaf 还提供了大量的 th 属性，这些属性可以直接在 HTML 标签中使用</li>
</ul>
</li>
</ul>
</li>
<li><p>Thymeleaf 公共页面抽取（在 Web 项目中，通常会存在一些公共页面片段（重复代码），例如头部导航栏、侧边菜单栏和公共的 js css 等。我们一般会把这些公共页面片段抽取出来，存放在一个独立的页面中，然后再由其他页面根据需要进行引用，这样可以消除代码重复，使页面更加简洁）</p>
<ul>
<li><p>抽取公共页面</p>
<ul>
<li>Thymeleaf 作为一种优雅且高度可维护的模板引擎，同样支持公共页面的抽取和引用。我们可以将公共页面片段抽取出来，存放到一个独立的页面中，并使用 Thymeleaf 提供的 th:fragment 属性为这些抽取出来的公共页面片段命名。 </li>
</ul>
</li>
<li><p>引用公共页面</p>
<ul>
<li>在 Thymeleaf 中，我们可以使用以下 3 个属性，将公共页面片段引入到当前页面中。<ul>
<li>th:insert：将代码块片段整个插入到使用了 th:insert 属性的 HTML 标签中；</li>
<li>th:replace：将代码块片段整个替换使用了 th:replace 属性的 HTML 标签中；</li>
<li>th:include：将代码块片段包含的内容插入到使用了 th:include 属性的 HTML 标签中。</li>
</ul>
</li>
<li>使用上 3 个属性引入页面片段，都可以通过以下 2 种方式实现。<ul>
<li>~{templatename::selector}：模板名::选择器</li>
<li>~{templatename::fragmentname}：模板名::片段名</li>
<li>通常情况下，<del>{} 可以省略，其行内写法为 [[</del>{…}]] 或 [(<del>{…})]，其中  [[</del>{…}]] 会转义特殊字符，[(~{…})] 则不会转义特殊字符。</li>
</ul>
</li>
</ul>
</li>
<li><p>传递参数</p>
<ul>
<li><p>传入参数</p>
<ul>
<li><p>引用公共页面片段时，我们可以通过以下 2 种方式，将参数传入到被引用的页面片段中：</p>
  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">模板名::选择器名或片段名(参数1=参数值1,参数2=参数值2)</span><br><span class="line">模板名::选择器名或片段名(参数值1,参数值2)</span><br></pre></td></tr></table></figure></li>
<li><p>注：</p>
</li>
<li><p>若传入参数较少时，一般采用第二种方式，直接将参数值传入页面片段中；</p>
</li>
<li><p>若参数较多时，建议使用第一种方式，明确指定参数名和参数值</p>
</li>
</ul>
</li>
<li><p>使用参数</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot整合Thymeleaf"><a href="#Spring-Boot整合Thymeleaf" class="headerlink" title="Spring Boot整合Thymeleaf"></a>Spring Boot整合Thymeleaf</h3><ul>
<li>Spring Boot 推荐使用 Thymeleaf 作为其模板引擎。SpringBoot 为 Thymeleaf 提供了一系列默认配置，项目中一但导入了 Thymeleaf 的依赖，相对应的自动配置 （ThymeleafAutoConfiguration 或 FreeMarkerAutoConfiguration） 就会自动生效，因此 Thymeleaf 可以与 Spring Boot 完美整合 </li>
<li>Spring Boot 整合 Thymeleaf 模板引擎，需要以下步骤：<ol>
<li>引入 Starter 依赖</li>
<li>创建模板文件，并放在在指定目录下</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot国际化"><a href="#Spring-Boot国际化" class="headerlink" title="Spring Boot国际化"></a>Spring Boot国际化</h3><ul>
<li><p>国际化（Internationalization 简称 I18n，其中“I”和“n”分别为首末字符，18 则为中间的字符数）是指软件开发时应该具备支持多种语言和地区的功能。换句话说就是，开发的软件需要能同时应对不同国家和地区的用户访问，并根据用户地区和语言习惯，提供相应的、符合用具阅读习惯的页面和数据，例如，为中国用户提供汉语界面显示，为美国用户提供提供英语界面显示。</p>
</li>
<li><p>在 Spring 项目中实现国际化，通常需要以下 3 步：</p>
<ol>
<li><p>编写国际化资源（配置）文件；</p>
<ul>
<li><p>在 Spring Boot  的类路径下创建国际化资源文件，文件名格式为：基本名_语言代码_国家或地区代码，例如 login_en_US.properties、login_zh_CN.properties。</p>
</li>
<li><p>以 spring-boot-springmvc-demo1为例，在 src/main/resources 下创建一个 i18n 的目录，并在该目录中按照国际化资源文件命名格式分别创建以下三个文件，</p>
  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">login.properties：无语言设置时生效</span><br><span class="line">login_en_US.properties ：英语时生效</span><br><span class="line">login_zh_CN.properties：中文时生效</span><br></pre></td></tr></table></figure></li>
<li><p>以上国际化资源文件创建完成后，IDEA 会自动识别并转换</p>
</li>
</ul>
</li>
<li><p>使用 ResourceBundleMessageSource 管理国际化资源文件；</p>
</li>
<li><p>在页面获取国际化内容。</p>
</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot拦截器"><a href="#Spring-Boot拦截器" class="headerlink" title="Spring Boot拦截器"></a>Spring Boot拦截器</h3><ul>
<li><p>拦截器功能：根据 URL 对请求进行拦截，主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能上。</p>
</li>
<li><p>Spring Boot 同样提供了拦截器功能。 </p>
</li>
<li><p>在 Spring Boot 项目中，使用拦截器功能通常需要以下 3 步：</p>
<ol>
<li><p>定义拦截器；</p>
<ul>
<li>在 Spring Boot 中定义拦截器十分的简单，只需要创建一个拦截器类，并实现 HandlerInterceptor 接口即可。</li>
<li>HandlerInterceptor  接口中定义以下 3 个方法，如下表。</li>
</ul>
<table>
<thead>
<tr>
<th align="left">方法</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody><tr>
<td align="left">preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)</td>
<td align="left">该方法在控制器处理请求方法前执行，其返回值表示是否中断后续操作，返回 true 表示继续向下执行，返回 false 表示中断后续操作。</td>
</tr>
<tr>
<td align="left">postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</td>
<td align="left">该方法在控制器处理请求方法调用之后、解析视图之前执行，可以通过此方法对请求域中的模型和视图做进一步修改。</td>
</tr>
<tr>
<td align="left">afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</td>
<td align="left">该方法在视图渲染结束后执行，可以通过此方法实现资源清理、记录日志信息等工作。</td>
</tr>
</tbody></table>
</li>
<li><p>注册拦截器；</p>
<ul>
<li>创建一个实现了 WebMvcConfigurer 接口的配置类（使用了 @Configuration 注解的类），重写 addInterceptors() 方法，并在该方法中调用 registry.addInterceptor() 方法将自定义的拦截器注册到容器中。</li>
</ul>
</li>
<li><p>指定拦截规则（如果是拦截所有，静态资源也会被拦截）。</p>
<ul>
<li>在指定拦截器拦截规则时，调用了两个方法，这两个方法的说明如下：<ul>
<li>addPathPatterns：该方法用于指定拦截路径，例如拦截路径为“/**”，表示拦截所有请求，包括对静态资源的请求。</li>
<li>excludePathPatterns：该方法用于排除拦截路径，即指定不需要被拦截器拦截的请求。</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot默认异常处理"><a href="#Spring-Boot默认异常处理" class="headerlink" title="Spring Boot默认异常处理"></a>Spring Boot默认异常处理</h3><h4 id="Spring-Boot-默认异常处理机制"><a href="#Spring-Boot-默认异常处理机制" class="headerlink" title="Spring Boot 默认异常处理机制"></a>Spring Boot 默认异常处理机制</h4><ul>
<li>Spring Boot 提供了一套默认的异常处理机制，一旦程序中出现了异常，Spring Boot 会自动识别客户端的类型（浏览器客户端或机器客户端），并根据客户端的不同，以不同的形式展示异常信息。<ol>
<li>对于浏览器客户端而言，Spring Boot 会响应一个“ whitelabel”错误视图，以 HTML 格式呈现错误信息</li>
<li>对于机器客户端而言，Spring Boot 将生成 JSON 响应，来展示异常消息</li>
</ol>
</li>
</ul>
<h4 id="Spring-Boot-异常处理自动配置原理"><a href="#Spring-Boot-异常处理自动配置原理" class="headerlink" title="Spring Boot 异常处理自动配置原理"></a>Spring Boot 异常处理自动配置原理</h4><ul>
<li>Spring Boot 通过配置类 ErrorMvcAutoConfiguration 对异常处理提供了自动配置，该配置类向容器中注入了以下 4 个组件。<ul>
<li>ErrorPageCustomizer：该组件会在在系统发生异常后，默认将请求转发到“/error”上。</li>
<li>BasicErrorController：处理默认的“/error”请求。</li>
<li>DefaultErrorViewResolver：默认的错误视图解析器，将异常信息解析到相应的错误视图上。</li>
<li>DefaultErrorAttributes：用于页面上共享异常信息。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot全局异常处理"><a href="#Spring-Boot全局异常处理" class="headerlink" title="Spring Boot全局异常处理"></a>Spring Boot全局异常处理</h3><ul>
<li>定制错误页面<ul>
<li>自定义error.html</li>
<li>自定义动态错误页面</li>
<li>自定义静态错误页面</li>
</ul>
</li>
<li>错误页面优先级<ul>
<li>自定义动态错误页面（精确匹配）&gt;自定义静态错误页面（精确匹配）&gt;自定义动态错误页面（模糊匹配）&gt;自定义静态错误页面（模糊匹配）&gt;自定义 error.html</li>
</ul>
</li>
<li>定制错误数据<ol>
<li>自定义异常处理类，将请求转发到 “/error”，交由 Spring Boot 底层（BasicErrorController）进行处理，自动适配浏览器客户端和机器客户端。</li>
<li>通过继承 DefaultErrorAttributes 来定义一个错误属性处理工具，并在原来的基础上添加自定义的错误数据。</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot注册Web原生组件（Servlet、Filter、Listener）"><a href="#Spring-Boot注册Web原生组件（Servlet、Filter、Listener）" class="headerlink" title="Spring Boot注册Web原生组件（Servlet、Filter、Listener）"></a>Spring Boot注册Web原生组件（Servlet、Filter、Listener）</h3><ul>
<li>由于 Spring Boot 默认以 Jar 包方式部署的，默认没有 web.xml，因此无法再像以前一样通过 web.xml 配置来使用 Servlet 、Filter、Listener，但 Spring Boot 提供了 2 种方式来注册这些 Web 原生组件。<ul>
<li>通过组件扫描注册<ul>
<li>Servlet 3.0 提供了以下 3 个注解：<ul>
<li>@WebServlet：用于声明一个 Servlet；</li>
<li>@WebFilter：用于声明一个 Filter；</li>
<li>@WebListener：用于声明一个 Listener。</li>
</ul>
</li>
<li>这些注解可直接标注在对应组件上，它们与在 web.xml 中的配置意义相同。每个注解都具有与 web.xml 对应的属性，可直接配置，省去了配置 web.xml 的繁琐。</li>
<li>想要在 SpringBoot 中注册这些原生 Web 组件，可以使用 @ServletComponentScan 注解实现，该注解可以扫描标记 @WebServlet、@WebFilter 和 @WebListener  三个注解的组件类，并将它们注册到容器中。</li>
<li>注意：@ServletComponentScan 注解只能标记在启动类或配置类上。</li>
</ul>
</li>
<li>使用 RegistrationBean 注册<ul>
<li>我们还可以在配置类中使用 RegistrationBean 来注册原生 Web 组件，不过这种方式相较于注解方式要繁琐一些。使用这种方式注册的原生 Web 组件，不再需要使用 @WebServlet 、@WebListener 和 @WebListener 等注解。</li>
<li>RegistrationBean 是个抽象类，负责将组件注册到 Servlet 容器中，Spring 提供了三个它的实现类，分别用来注册 Servlet、Filter 和 Listener。<ul>
<li>ServletRegistrationBean：Servlet 的注册类</li>
<li>FilterRegistrationBean：Filter 的注册类</li>
<li>ServletListenerRegistrationBean：Listener 的注册类</li>
</ul>
</li>
<li>我们可以在配置类中，使用 @Bean 注解将 ServletRegistrationBean、FilterRegistrationBean 和 ServletListenerRegistrationBean 添加 Spring 容器中，并通过它们将我们自定义的 Servlet、Filter 和 Listener 组件注册到容器中使用。 </li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot-JDBC访问数据库"><a href="#Spring-Boot-JDBC访问数据库" class="headerlink" title="Spring Boot JDBC访问数据库"></a>Spring Boot JDBC访问数据库</h3><ul>
<li>对于数据访问层，无论是 SQL（关系型数据库） 还是 NOSQL（非关系型数据库），Spring Boot 都默认采用整合 Spring Data 的方式进行统一处理，通过大量自动配置，来简化我们对数据访问层的操作，我们只需要进行简单的设置即可实现对书层的访问。<ul>
<li>导入 JDBC 场景启动器<ul>
<li>Spring Boot 将日常企业应用研发中的各种场景都抽取出来，做成一个个的场景启动器（Starter），场景启动器中整合了该场景下各种可能用到的依赖，让用户摆脱了处理各种依赖和配置的困扰</li>
</ul>
</li>
<li>导入数据库驱动<ul>
<li>JDBC 的场景启动器中并没有导入数据库驱动，我们需要根据自身的需求引入所需的数据库驱动。例如，访问 MySQL 数据库时，需要导入 MySQL 的数据库驱动：mysql-connector-java</li>
</ul>
</li>
<li>配置数据源<ul>
<li>在导入了 JDBC 场景启动器和数据库驱动后，接下来我们就可以在配置文件（application.properties/yml）中配置数据源</li>
</ul>
</li>
<li>测试<ul>
<li>Spring Boot 提供了一个名为 JdbcTemplate 的轻量级数据访问工具，它是对 JDBC 的封装。Spring Boot 对 JdbcTemplate 提供了默认自动配置，我们可以直接使用 @Autowired 或构造函数将它注入到 bean 中使用</li>
</ul>
</li>
</ul>
</li>
<li>Spring Boot数据源配置原理<ul>
<li>DataSourceAutoConfiguration：Spring Boot 数据源的自动配置类，共包括以下 5 个内部静态类<ul>
<li>EmbeddedDatabaseCondition</li>
<li>PooledDataSourceAvailableCondition</li>
<li>PooledDataSourceCondition</li>
<li>PooledDataSourceConfiguration（池化数据源自动配置类）</li>
<li>EmbeddedDatabaseConfiguration（内嵌数据源自动配置类）</li>
<li>PooledDataSourceConfiguration 和 EmbeddedDatabaseConfiguration 为使用了 @Configuration 注解的自动配置类，其余 3 个为限制条件类</li>
</ul>
</li>
<li>在用户没有配置数据源的情况，若容器中存在 HikariDataSource 类，则 Spring Boot 就会自动实例化 Hikari，并将其作为其数据源。</li>
<li>Spring Boot 的 JDBC 场景启动器（spring-boot-starter-data-jdbc）通过 spring- boot-starter-jdbc 默认引入了 HikariCP 数据源（包含 HikariDataSource 类），因此 Spring Boot 默认使用 HikariCP 作为其数据源。</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot整合Druid数据源"><a href="#Spring-Boot整合Druid数据源" class="headerlink" title="Spring Boot整合Druid数据源"></a>Spring Boot整合Druid数据源</h3><ul>
<li>Spring Boot 2.x 默认使用 HikariCP 作为数据源，我们只要在项目中导入了 Spring Boot 的 JDBC 场景启动器，便可以使用 HikariCP 数据源获取数据库连接，对数据库进行增删改查等操作。</li>
<li>HikariCP 是目前市面上性能最好的数据源产品，但在实际的开发过程中，企业往往更青睐于另一款数据源产品：Druid，它是目前国内使用范围最广的数据源产品。</li>
<li>Druid 是阿里巴巴推出的一款开源的高性能数据源产品，Druid 支持所有 JDBC 兼容的数据库，包括 Oracle、MySQL、SQL Server 和 H2 等等。Druid 不仅结合了 C3P0、DBCP 和 PROXOOL 等数据源产品的优点，同时还加入了强大的监控功能。通过 Druid 的监控功能，可以实时观察数据库连接池和 SQL 的运行情况，帮助用户及时排查出系统中存在的问题。</li>
<li>Druid 不是 Spring Boot 内部提供的技术，它属于第三方技术，我们可以通过以下两种方式进行整合：<ul>
<li>自定义整合 Druid ：根据 Druid 官方文档和自身的需求，通过手动创建 Druid 数据源的方式，将 Druid 整合到 Spring Boot 中<ol>
<li>引入 Druid 依赖</li>
<li>创建数据源</li>
<li>开启 Druid 内置监控页面</li>
<li>开启 SQL 监控</li>
<li>开启防火墙</li>
<li>开启 Web-JDBC 关联监控</li>
</ol>
</li>
<li>通过 starter 整合 Druid ：阿里官方提供了 Druid Spring Boot Starter，它可以帮助我们在 Spring Boot 项目中，轻松地整合 Druid 的数据库连接池和监控功能<ol>
<li>引入 Druid Spring Boot Starter 依赖</li>
<li>配置属性</li>
</ol>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="Spring-Boot整合MyBatis"><a href="#Spring-Boot整合MyBatis" class="headerlink" title="Spring Boot整合MyBatis"></a>Spring Boot整合MyBatis</h3><ul>
<li>MyBatis 是一个半自动化的 ORM 框架，所谓半自动化是指 MyBatis 只支持将数据库查出的数据映射到 POJO 实体类上，而实体到数据库的映射则需要我们自己编写 SQL 语句实现，相较于Hibernate 这种完全自动化的框架，Mybatis 更加灵活，我们可以根据自身的需求编写 sql 语句来实现复杂的数据库操作。</li>
<li>在 Spring Boot 项目中整合 MyBatis<ol>
<li>引入依赖</li>
<li>配置 MyBatis</li>
<li>创建实体类</li>
<li>创建 Mapper 接口</li>
<li>创建 Mapper 映射文件</li>
</ol>
</li>
</ul>
<hr>
<h3 id="Spring-Boot自定义starter"><a href="#Spring-Boot自定义starter" class="headerlink" title="Spring Boot自定义starter"></a>Spring Boot自定义starter</h3><ul>
<li><p>starter 是 SpringBoot 中一种非常重要的机制，它可以繁杂的配置统一集成到 starter 中，我们只需要通过 maven 将 starter 依赖引入到项目中，SpringBoot 就能自动扫描并加载相应的默认配置。starter 的出现让开发人员从繁琐的框架配置中解放出来，将更多的精力专注于业务逻辑的开发，极大的提高了开发效率。</p>
</li>
<li><p>在一些特殊情况下，我们也可以将一些通用功能封装成自定义的 starter 进行使用，本节我们将为您详细介绍如何自定义 starter。</p>
</li>
</ul>
<h4 id="命名规范"><a href="#命名规范" class="headerlink" title="命名规范"></a>命名规范</h4><ul>
<li>SpringBoot 提供的 starter 以 spring-boot-starter-xxx 的形式命名。为了与 SpringBoot 生态提供的 starter 进行区分，官方建议第三方开发者或技术（例如 Druid、Mybatis 等等）厂商自定义的 starter 使用 xxx-spring-boot-starter 的形式命名，例如 mybatis-spring-boot-starter、druid-spring-boot-starter 等等。 </li>
</ul>
<h4 id="模块规范"><a href="#模块规范" class="headerlink" title="模块规范"></a>模块规范</h4><ul>
<li>Spring Boot 官方建议我们在自定义 starter 时，创建两个 Module ：autoConfigure Module 和 starter Module，其中 starter Module 依赖于 autoConfigure Module。当然，这只是 Spring Boot 官方的建议，并不是硬性规定，若不需要自动配置代码和依赖项目分离，我们也可以将它们组合到同一个 Module 里。 </li>
</ul>
<h4 id="自定义-starter"><a href="#自定义-starter" class="headerlink" title="自定义 starter"></a>自定义 starter</h4><ul>
<li>自定义 starter 可以分为以下 7 步：<ol>
<li>创建工程</li>
<li>添加 POM 依赖</li>
<li>定义 propertie 类</li>
<li>定义 Service 类</li>
<li>定义配置类</li>
<li>创建 spring.factories文件</li>
<li>构建 starter</li>
</ol>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2022/01/14/SpringBoot/" data-id="ckymzfig30002gsv3de6z01yc" data-title="SpringBoot" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2022/01/16/MyBatis/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          MyBatis
        
      </div>
    </a>
  
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2022/01/">January 2022</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2022/01/20/hello-world/">Hello World</a>
          </li>
        
          <li>
            <a href="/2022/01/20/Spring/">Spring</a>
          </li>
        
          <li>
            <a href="/2022/01/17/SpringMVC/">Spring MVC</a>
          </li>
        
          <li>
            <a href="/2022/01/16/MyBatis/">MyBatis</a>
          </li>
        
          <li>
            <a href="/2022/01/14/SpringBoot/">SpringBoot</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.4.1.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>